﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OmniKits
{
    using Utilities;

    partial class Helpers
    {
        public sealed class TypeHelper { }
        public static TypeHelper TypeEx { get; }

        public static Type GetType<T>(this TypeHelper _)
            => TypeUtility<T>.Type;
        public static bool GetIsClass<T>(this TypeHelper _)
            => TypeUtility<T>.IsClass;
        public static bool GetIsValueType<T>(this TypeHelper _)
            => TypeUtility<T>.IsValueType;
        public static bool GetIsReferenceType<T>(this TypeHelper _)
            => TypeUtility<T>.IsReferenceType;
        public static bool GetIsGenericType<T>(this TypeHelper _)
            => TypeUtility<T>.IsGenericType;
        public static bool GetIsGenericTypeDefinition<T>(this TypeHelper _)
            => TypeUtility<T>.IsGenericTypeDefinition;
        public static bool GetIsNullable<T>(this TypeHelper _)
            => TypeUtility<T>.IsNullable;
        public static bool GetIsNullAssignable<T>(this TypeHelper _)
            => TypeUtility<T>.IsNullAssignable;
    }
}

namespace OmniKits.Utilities
{
    public static class TypeUtility<T>
    {
        public static Type Type { get; }
        public static bool IsClass { get; }
        public static bool IsValueType { get; }
        public static bool IsReferenceType { get; }
        public static bool IsGenericType { get; }
        public static bool IsGenericTypeDefinition { get; }
        public static bool IsNullable { get; }
        public static bool IsNullAssignable { get; }

        static TypeUtility()
        {
            var Type = typeof(T);
            IsClass = Type.IsClass;
            IsValueType = Type.IsValueType;
            IsReferenceType = !IsValueType;
            IsGenericType = Type.IsGenericType;
            IsGenericTypeDefinition = Type.IsGenericTypeDefinition;
            IsNullable = IsGenericType && Type.GetGenericTypeDefinition() == typeof(Nullable<>);
            IsNullAssignable = IsReferenceType || IsNullable;
        }
    }
}
